<?php
namespace App\Models\Admin;

use App\admin\Service\OA;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
/**
 * @property int10unsigned id
 * @property varchar255 api
 * @property varchar255 call
 * @property int auth
 * @property int10unsigned count
 * @property int10unsigned isrun
 * @property int10unsigned success
 * @property int11unsigned fail
 * @property varchar255 notes
 * @property varchar255 name
 * @property int11unsigned runtime
 */
class ApilistModel extends BaseModel
{
    /**
     * 管理员
     */

    protected $table = 'apilist';
    protected $fillable = [
        'id','api','call','auth','count','isrun','success','fail',
        'notes','name','runtime',
    ];

    const auth_all=0;///无权限要求，任何用户可以使用
    const auth_user=1;///必须是登录用户
    const auth_role=2;///根据角色组决定



    public static function getAuthArray($key=null){
        $list=[
            self::auth_all=>'全部',
            self::auth_user=>'登录用户',
            self::auth_role=>'角色组'
        ];
        if($key===null){
            return $list;
        }else{
            return isset($list[$key])?$list[$key]:$key;
        }
    }

    public function attributeLabels() {
        return [
            'id' => 'id',
            'api' => '接口字符串',
            'call' => '调用的类和成员',
            'auth' => '授权',//
            'count' => '调用次数',
            'isrun' => '启用',///如果为0，表示禁止执行，非0表示可以执行
            'success' => '成功',
            'fail' => '失败',
            'notes' => '注释',
            'name'=>'名字',
            'average_time'=>'平均耗时',
            'runtest'=>'测试'
        ];
    }
    public static function callAPI($strApi,Request $request)
    {
        // print_r($_SERVER);exit;


        $beginTime=microtime(true)*1000;
        //OA::load();
        /**
         * @var $apiObj ApilistModel
         */
        $apiObj=self::where(['api'=>$strApi])->first();
        if(!$apiObj){
            OA::Json(1,'接口调用失败，没有相关接口'.$strApi);
        }
        if($apiObj->isrun==0){
           /* LogModel::Add($apiObj->id,'接口调用失败，该接口被禁止使用'.$strApi,LogModel::state_fail,
                microtime(true)*1000-$beginTime);*/
            OA::Json(1,'接口调用失败，该接口被禁止使用'.$strApi);
        }
        //  var_dump($apiObj['name'],$apiObj->auth);exit;
        if($apiObj->auth!==self::auth_all){///如果不是全部授权，则进一步判断
            if(OA::$user->isGuest()){///如果没有登录，返回授权失败
               /* LogModel::Add($apiObj->id,'接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限',
                    LogModel::state_fail,
                    microtime(true)*1000-$beginTime);*/
                OA::Json(OA::Guest,'接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限');
            }
            if($apiObj->auth===self::auth_role){///如果是角色组类型
                if(!OA::$user->validateRole($apiObj->id)){
                  /*  LogModel::Add($apiObj->id,'已经登录用户；接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限'
                        ,LogModel::state_fail,
                        microtime(true)*1000-$beginTime);*/
                    OA::Json(1,'已经登录用户；接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限');
                }
            }

        }

        $apiObj->count++;
        $call=$apiObj->call;
        if($call==''){
            $apiObj->fail++;
            $apiObj->runtime+=(int)(microtime(true)*1000-$beginTime);
            $apiObj->save();
            /*LogModel::Add($apiObj->id,'接口调用失败，该接口调用路径为空'
                ,LogModel::state_fail,
                microtime(true)*1000-$beginTime);*/
            OA::Json(1,'接口调用失败，该接口调用路径为空');
            return;
        }
        $isStatic=false;
        $apilist=explode('@',$call);
        if(count($apilist)==1){
            $apilist=explode('::',$call);
            if(count($apilist)==2){
                $isStatic=true;
            }
        }

        $className=$apilist[0];
        $classCall=isset($apilist[1])?$apilist[1]:null;
        if(!class_exists($className)){
           /* LogModel::Add($apiObj->id,'接口调用失败，接口类不存在'
                ,LogModel::state_fail,
                microtime(true)*1000-$beginTime);*/
            OA::Json(1,'接口调用失败，接口类不存在'.$className);
        }

        try {


            $isSave=false;
            /**
             * @var $isSuccess 表示是否执行成功，
             */
            OA::RunCall(function($isSuccess,$content='') use (&$apiObj,&$isSave,&$beginTime) {
                if($isSave){
                    return;
                }
                $isSave=true;
                if($isSuccess){
                    $apiObj->success++;
                  //  $state=LogModel::state_success;
                }else{
                    $apiObj->fail++;
                 //   $state=LogModel::state_fail;
                }
               // exit('aadsgaf');
                OA::$_SQL=DB::getQueryLog();
               // LogModel::Add($apiObj->id,$content  ,$state, microtime(true)*1000-$beginTime);
                $apiObj->runtime+=(int)(microtime(true)*1000-$beginTime);
              //  var_dump($apiObj->runtime);exit;
                $apiObj->save();
            });
            DB::enableQueryLog();
            $json=[];
            if($isStatic){
                $json=$className::$classCall();
            }else{
                $new=new $className($strApi);
                //$new->load();
                if($classCall){
                    //var_dump($className,$new,$classCall);exit;
                    $json=$new->$classCall($request);
                }
            }



            if($isSave){
                return;
            }
            OA::$_SQL=DB::getQueryLog();
            $isSave=true;
            $apiObj->success++;
            $apiObj->runtime+=microtime(true)*1000-$beginTime;
          //  LogModel::Add($apiObj->id,OA::$_apiMsg,LogModel::state_null, microtime(true)*1000-$beginTime);
            $apiObj->save();
            OA::Json(0,$json);
        } catch (Exception $e) {
            $apiObj->fail++;
            $apiObj->runtime+=microtime(true)*1000-$beginTime;
          //  LogModel::Add($apiObj->id,$e->getMessage() ,LogModel::state_fail, microtime(true)*1000-$beginTime);
            $apiObj->save();
            OA::Json(1,'接口调用失败'.$e->getMessage());
        }
    }




    /**
     * 返回接口测试结果
     */
    public static function getTest($model){
        $apilist=explode('@',$model->call);
        $className=$apilist[0];
        try{
            if(!class_exists($className)){
                return '接口配置错误，没有找到该类'.$className;
            }
            $new=new $className($className);
            if(!method_exists($new,'test')){
                return '接口配置错误，没有继承ApiBase';
            }
            return $new->test();
        }catch (\Exception $e){
            return '接口配置错误，没有继承ApiBase';
        }catch (ThrowableError $e){
            return '接口配置错误，没有继承ApiBase';
        }

    }

    /**
     * 返回所有的接口列表
     */
    public static function getList(){
        $list=self::where([
            'auth'=>self::auth_role
        ])->all();
        $array=[];
        //print_r($list);exit;
        foreach ($list as $item) {
            $array[$item['id']]=$item['name'];
        }
        return $array;
    }


    static $_cachename=[];
    public static function idToName($id){
        if(empty($id)){
            return '系统';
        }
        if(isset(self::$_cachename[$id])){
            return self::$_cachename[$id];
        }
        $one=self::find($id);
        if($one){
            return self::$_cachename[$id]=$one['name'];
        }else{
            return '接口被删除';
        }
    }
}